package com.yanqu.road.server.manger.config.grandchild;

import com.yanqu.road.dao.impl.config.GrandChildTalentInfoDaoImpl;
import com.yanqu.road.entity.config.beauty.BeautyIdentityInfo;
import com.yanqu.road.entity.config.children.ChildTalentInfo;
import com.yanqu.road.entity.config.goods.GoodsInfo;
import com.yanqu.road.entity.config.grandchild.GrandChildTalentInfo;
import com.yanqu.road.entity.config.patrons.PatronsInfo;
import com.yanqu.road.entity.config.skill.SkillInfo;
import com.yanqu.road.entity.config.skill.SkillUpgradeInfo;
import com.yanqu.road.entity.enums.eGamePlayerEventType;
import com.yanqu.road.entity.enums.eLogMoneyType;
import com.yanqu.road.entity.enums.eOccupationType;
import com.yanqu.road.entity.enums.eSkillType;
import com.yanqu.road.entity.grandchild.GrandChildData;
import com.yanqu.road.entity.grandchild.GrandChildOneKeyResult;
import com.yanqu.road.entity.log.LogGrandChildRefreshTalent;
import com.yanqu.road.entity.marriage.MarriageRecord;
import com.yanqu.road.entity.player.UserBeauty;
import com.yanqu.road.logic.bussiness.grandchild.GrandChildBussiness;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.logic.helper.CalcPowerResult;
import com.yanqu.road.logic.helper.PowerHelper;
import com.yanqu.road.server.GameServer;
import com.yanqu.road.server.TempMgr;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.grandson.GrandChildModule;
import com.yanqu.road.server.gameplayer.module.grandson.GrandChildUpgradeResult;
import com.yanqu.road.server.gameplayer.module.patrons.PatronsModule;
import com.yanqu.road.server.gameplayer.module.player.BeautyModule;
import com.yanqu.road.server.gameplayer.module.player.CurrencyModule;
import com.yanqu.road.server.manger.ServerListMgr;
import com.yanqu.road.server.manger.VipMgr;
import com.yanqu.road.server.manger.config.*;
import com.yanqu.road.server.manger.config.grandchild.skill.GrandChildSkillUtils;
import com.yanqu.road.server.manger.config.grandchild.talent.entity.TalentTriggerResult;
import com.yanqu.road.server.manger.config.grandchild.talent.enums.eGrandChildSkillEffectStage;
import com.yanqu.road.server.manger.config.grandchild.talent.utils.TalentResultUtils;
import com.yanqu.road.server.manger.config.grandchild.talent.utils.TalentUtils;
import com.yanqu.road.server.manger.log.AutoLogMgr;
import com.yanqu.road.server.manger.log.LogMgr;
import com.yanqu.road.server.manger.player.GamePlayerMgr;
import com.yanqu.road.utils.RandomHelper;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class GrandChildConfigMgr extends TempMgr {

    private static List<BigInteger> openSchoolSiteConsumerList;

    private static Map<Integer, GrandChildTalentInfo> grandChildTalentInfoMap;

    private static RandomHelper randomHelper = new RandomHelper();

    private static Property honeyMoonConsume;

    // 区服ID，分组ID
    private static Map<Long, Integer> serverGroupMap;
    // 分组ID，List区服ID
    private static Map<Integer, List<Long>> groupServerMap;


    public static void grandChildBorn(GamePlayer player, GrandChildData data, boolean isSave) {
        List<TalentTriggerResult> triggerResultList = TalentUtils.getTriggerTalentResult(data, com.yanqu.road.server.manger.config.grandchild.talent.enums.eGrandChildSkillEffectStage.CHOICE_TALENT);
        TalentResultUtils.applyTalentAttrChange(data, triggerResultList);

        //确认职业
        confirmOccupation(data);
        //判断是否升级
        for (int i = 0; i < data.getLv(); i++) {
            GrandChildUpgradeResult result = calcAddEarnSpeed(player, data, true);
            BigInteger addEarnSpeed = result.getAddEarnSpeed();
            getLogger().info("addSpeed : {}", addEarnSpeed);
            data.setEarnSpeed(data.getEarnSpeed().add(addEarnSpeed));
            if (isSave) {
                //孙子赚速冲榜
                player.notifyListener(eGamePlayerEventType.GrandChildEarnSpeedRiseRank.getValue(), addEarnSpeed);
//                player.notifyListener(eGamePlayerEventType.CrossGrandChildEarnSpeedRiseRank.getValue(), addEarnSpeed);
            }
        }
        boolean hasAffinity = false;
        List<Integer> talentList;
        if (isSave) {
            talentList = data.getTalentList();
        } else {
            talentList = data.getOptionalList();
        }
        for (Integer talentId : talentList) {
            GrandChildTalentInfo info = GrandChildConfigMgr.getGrandChildTalentInfo(talentId);
            for (Integer skillId : info.getSkills()) {
                SkillInfo skillInfo = SkillMgr.getSkillInfo(skillId);
                if (skillInfo != null) {
                    if (skillInfo.getType() == eSkillType.GrandChildPatronsAbilityAddi.getValue()) {
                        hasAffinity = true;
                        break;
                    }
                }
            }
        }
        if (!hasAffinity) {
            data.setAffinityPatronsId(0);
        }
    }

    public static void confirmOccupation(GrandChildData data) {
        List<Integer> flairList = data.getFlairList();
        List<Integer> maxIndex = new ArrayList<>();
        int maxValue = 0;
        for (int i = 0; i < flairList.size(); i++) {
            Integer value = flairList.get(i);
            if (value > maxValue) {
                maxIndex.clear();
                maxIndex.add(i);
                maxValue = value;
            } else if (value == maxValue) {
                maxIndex.add(i);
            }
        }
        int occupation = 1;
        if (maxIndex.size() >= 1) {
            occupation = maxIndex.get(0) + 1;
        }/* else if (maxIndex.size() > 1) {
            int i = data.AllBaseFlair() % maxIndex.size();
            occupation = maxIndex.get(i) + 1;
        }*/
        data.setOccupation(occupation);
        data.setAppearanceId(ChildMgr.getGrandChildAppearanceId(occupation + 100, data.getSex()));

    }

    public static int getGrandChildQuality(GamePlayer player, MarriageRecord record) {
        int maxTalent = Math.max(record.getChildTalent(), record.getPartnerChildTalent());
        ChildTalentInfo childTalentInfo = ChildMgr.getChildTalentInfo(maxTalent);
        List<Integer> grandsonQuality = childTalentInfo.getGrandsonQuality();
        int addition = player.getModule(PatronsModule.class).getTalentSkillAddition(eSkillType.GrandChildQualityWeightAddition.getValue(), 0);
        List<Integer> weightList = new ArrayList<>();
        for (int i = 0; i < grandsonQuality.size(); i++) {
            Integer weight = grandsonQuality.get(i);
            if (i + 1 >= 4) {
                weight = (int) (weight * (1 + addition / 1000.0));
            }
            weightList.add(weight);
        }
        return RandomHelper.getRandomIndexByWeight(weightList) + 1;
    }

    public static int getSchoolMaxSite() {
        return openSchoolSiteConsumerList.size();
    }

    public static Property getOpenSiteConsumer(int num) {
        return new Property(GameConfig.GAME_MONEY_INGOTS, openSchoolSiteConsumerList.get(num));
    }

    public static int getMaxArchaeus() {
        return GameConfig.GRAND_CHILD_ARCHAEUS_LIMIT;
    }

    public static int getInitArchaeus() {
        return GameConfig.GRAND_CHILD_ARCHAEUS_DEFAULT;
    }

    public static int calcGraduationNeedItemNum(GrandChildData childData) {
        GoodsInfo goodsInfo = GoodsMgr.getGoodsById(GameConfig.GRAND_CHILD_ARCHAEUS_RECOVER_ITEM_ID);
        int recoverValue = goodsInfo.getParamList().get(0).intValue();
        long needTotal = 0;
        int curLv = childData.getLv();
        int skillType = GrandChildConfigMgr.getSkillUpgradeType(childData.getQuality());
        SkillUpgradeInfo upgradeInfo = SkillMgr.getSkillUpgradeInfo(skillType, curLv);
        while (upgradeInfo != null && curLv < childData.getMaxLv()) {
            needTotal += upgradeInfo.getConsumeCount();
            curLv++;
            upgradeInfo = SkillMgr.getSkillUpgradeInfo(skillType, curLv);
        }
        needTotal -= childData.getArchaeus();
        if (needTotal <= 0) {
            return 0;
        }
        long needValue = needTotal % recoverValue == 0 ? needTotal / recoverValue : needTotal / recoverValue + 1;
        return (int) needValue;
    }

    /**
     * 抄上面的 孙子升满级需要多少精力
     *
     * @param childData
     * @return
     */
    public static long calcGraduationNeedArchaeus(GrandChildData childData) {
        GoodsInfo goodsInfo = GoodsMgr.getGoodsById(GameConfig.GRAND_CHILD_ARCHAEUS_RECOVER_ITEM_ID);
        int recoverValue = goodsInfo.getParamList().get(0).intValue();
        long needTotal = 0;
        int curLv = childData.getLv();
        int skillType = GrandChildConfigMgr.getSkillUpgradeType(childData.getQuality());
        SkillUpgradeInfo upgradeInfo = SkillMgr.getSkillUpgradeInfo(skillType, curLv);
        while (upgradeInfo != null && curLv < childData.getMaxLv()) {
            needTotal += upgradeInfo.getConsumeCount();
            curLv++;
            upgradeInfo = SkillMgr.getSkillUpgradeInfo(skillType, curLv);
        }
        needTotal -= childData.getArchaeus();
        if (needTotal <= 0) {
            return 0;
        }
        return needTotal;
    }

    public static List<Integer> randomTalentList(GamePlayer player, GrandChildData childData) {
        //先重置缘分门客
        childData.setAffinityPatronsId(0);
        int num = getOptionalTalentNum(player);
        List<Integer> list = new ArrayList<>();
        List<GrandChildTalentInfo> talentList = getTalentPool(childData);
        while (talentList.size() > 0 && list.size() < num) {
            int totalWeight = 0;
            for (GrandChildTalentInfo info : talentList) {
                totalWeight += info.getWeight();
            }
            List<Integer> needRemoveTalentList = new ArrayList<>();
            int randomValue = randomHelper.next(totalWeight);
            for (GrandChildTalentInfo info : talentList) {
                if (randomValue < info.getWeight()) {
                    list.add(info.getId());
                    needRemoveTalentList.add(info.getId());
                    needRemoveTalentList.addAll(info.getExcludeList());
                    for (Integer skillId : info.getSkills()) {
                        SkillInfo skillInfo = SkillMgr.getSkillInfo(skillId);
                        if (skillInfo != null) {
                            if (skillInfo.getType() == eSkillType.GrandChildPatronsAbilityAddi.getValue()) {
                                int patronsId = randomAffinityPatrons(skillInfo);
                                childData.setAffinityPatronsId(patronsId);
                            }
                        }
                    }
                    break;
                }
                randomValue -= info.getWeight();
            }
            for (Integer id : list) {
                talentList.removeIf(next -> next.getExcludeList().contains(id));
            }
            for (Integer id : needRemoveTalentList) {
                talentList.removeIf(next -> Objects.equals(next.getId(), id));
            }
        }
        return list;
    }

    private static int randomAffinityPatrons(SkillInfo skillInfo) {
        List<Integer> paramList = skillInfo.getParamList();
        Integer patronsType = paramList.get(2);
        Integer patronsQuality = paramList.get(3);
        List<Integer> patronsList = PatronsMgr.getPatronsListByTypeAndQuality(patronsType, patronsQuality);
        if (patronsList.size() > 0) {
            int next = randomHelper.next(patronsList.size());
            return patronsList.get(next);
        }
        return 0;
    }

    private static int getOptionalTalentNum(GamePlayer player) {
        String[] arr = GameConfig.GRAND_CHILD_TATENT_OPTIONAL_SIZE_VIP.split(";");
        int vipLimit = Integer.parseInt(arr[0]);
        int num = Integer.parseInt(arr[1]);
        int vipLv = VipMgr.getVipLv(player.getUserInfo().getVipExp());
        if (vipLv >= vipLimit) {
            return num;
        }
        return GameConfig.GRAND_CHILD_TATENT_OPTIONAL_SIZE;
    }

    /**
     * 获取可以随机的天赋池
     *
     * @param childData
     * @return
     */
    private static List<GrandChildTalentInfo> getTalentPool(GrandChildData childData) {
        List<GrandChildTalentInfo> list = new ArrayList<>();
        for (GrandChildTalentInfo talentInfo : grandChildTalentInfoMap.values()) {
            if (!checkRightTalentInfo(talentInfo)) {
                continue;
            }
            if (GrandChildSkillUtils.canRandom(childData, talentInfo.getCondition())) {
                list.add(talentInfo);
            }
        }
        return list;
    }

    private static boolean checkRightTalentInfo(GrandChildTalentInfo talentInfo) {
        for (Integer id : talentInfo.getSkills()) {
            SkillInfo skillInfo = SkillMgr.getSkillInfo(id);
            if (skillInfo.getType() == eSkillType.GrandChildPatronsAbilityAddi.getValue()) {
                //如果是授学加成
                int patronsId = randomAffinityPatrons(skillInfo);
                if (patronsId == 0) {
                    return false;
                }
            }
        }
        return true;
    }

    private static boolean passTalentCondition(GrandChildData childData, GrandChildTalentInfo talentInfo) {
        String condition = talentInfo.getCondition();
        if (Objects.equals("0", condition)) {
            return true;
        } else {
            int quality = childData.getQuality();
            if (quality < Integer.parseInt(condition.split("<")[1])) {
                return true;
            }
        }
        return false;
    }

    public static int getTalentNumLimit(GamePlayer player) {
        int vipLv = VipMgr.getVipLv(player.getUserInfo().getVipExp());
        String[] arr = GameConfig.GRAND_CHILD_SELECT_TALENT_NUM_VIP.split(";");
        int needVip = Integer.parseInt(arr[0]);
        if (vipLv >= needVip) {
            return Integer.parseInt(arr[1]);
        }
        return GameConfig.GRAND_CHILD_SELECT_TALENT_NUM;
    }

    public static int getSkillUpgradeType(int quality) {
        String[] arr = GameConfig.GRAND_CHILD_QUALITY_UP_LV_PARAM.split("\\|");
        return Integer.parseInt(arr[quality - 1]);
    }

    public static int getMaxLv(int quality) {
        String[] arr = GameConfig.GRAND_CHILD_QUALITY_UP_LV_PARAM.split("\\|");
        int type = Integer.parseInt(arr[quality - 1]);
        return SkillMgr.getSkillMaxLvByUpgradeType(type);
    }

    public static Property getHoneyMoonConsume() {
        return new Property(honeyMoonConsume);
    }

    /**
     * 获取刷新列表消耗
     * 超过最大次数 取最后一次
     *
     * @param reTalentTimes
     * @return
     */
    public static Property getReTalentConsume(int reTalentTimes) {
        String[] arr = GameConfig.GRAND_CHILD_REELECTION_TALENT_CONSUME.split(";");
        if (reTalentTimes >= arr.length) {
            reTalentTimes = arr.length - 1;
        }
        if (Integer.parseInt(arr[reTalentTimes]) == 0) {
            return null;
        }
        return new Property(GameConfig.GRAND_CHILD_REELECTION_TALENT_CONSUME_ITEM_ID, new BigInteger(arr[reTalentTimes]));
    }

    public static boolean isFreeSite(int num) {
        if (num >= openSchoolSiteConsumerList.size() || num < 0) {
            return false;
        }
        return openSchoolSiteConsumerList.get(num).compareTo(BigInteger.ZERO) <= 0;
    }

    public static void initQualityAndMaxLv(GamePlayer player,MarriageRecord record, GrandChildData childData) {
        int quality = getGrandChildQuality(player,record);
        resetQualityAndMaxLv(childData, quality);
    }

    private static void resetQualityAndMaxLv(GrandChildData childData, int quality) {
        childData.setQuality(quality);
        String[] arr = GameConfig.GRAND_CHILD_QUALITY_LV.split("\\|");
        childData.setMaxLv(Integer.parseInt(arr[quality - 1]));
    }

    public static List<Integer> initFlairList(GamePlayer player, MarriageRecord record, GrandChildData childData) {
        List<Integer> list = new ArrayList<>();
        int baseTalent = calcBaseTalent(record, childData);

        String[] allotParamArr = GameConfig.GRAND_CHILD_TALENT_ALLOT_PARAM.split("\\|");
        int param1 = Integer.parseInt(allotParamArr[0]);
        int param2 = Integer.parseInt(allotParamArr[1]);
        List<Double> weightList = new ArrayList<>();
        double totalWeight = 0;
        for (eOccupationType occupationType : eOccupationType.values()) {
            int i = (int) occupationType.getValue();
            double value = randomHelper.next(0, 100);
            if (i == record.getChildOccupation() && i == record.getPartnerChildOccupation()) {
                value = new BigDecimal(value + param1 * 2).multiply(BigDecimal.ONE.add(BigDecimal.valueOf(param2 * 2).divide(BigDecimal.valueOf(1000), 4, BigDecimal.ROUND_UP))).doubleValue();
            } else if (i == record.getChildOccupation() || i == record.getPartnerChildOccupation()) {
                value = new BigDecimal(value + param1).multiply(BigDecimal.ONE.add(BigDecimal.valueOf(param2).divide(BigDecimal.valueOf(1000), 4, BigDecimal.ROUND_UP))).doubleValue();
            }
            weightList.add(value);
            totalWeight += value;
        }
        for (Double weight : weightList) {
            double value = weight / totalWeight * baseTalent;
            long round = Math.round(value);
            if (round <= 0) {
                round = 1;
            }
            list.add((int) round);
        }
        int nowTotal = 0;
        for (Integer value : list) {
            nowTotal += value;
        }
        int disValue = baseTalent - nowTotal;
        List<Integer> disList = new ArrayList<>();
        for (int i = 0; i < list.size(); i++) {
            if (list.get(i) + disValue > 0) {
                disList.add(i);
            }
        }
        List<Integer> newList = new ArrayList<>();

        if (disList.size() > 0) {
            int index = randomHelper.next(0, disList.size());
            Integer i = disList.get(index);
            for (int j = 0; j < list.size(); j++) {
                if (j == i) {
                    newList.add(list.get(j) + disValue);
                } else {
                    newList.add(list.get(j));
                }
            }
        } else {
            newList.addAll(list);
        }

        //加下美女美名的加成
        List<Integer> finalList = new ArrayList<>();
        for (int i = 0; i < newList.size(); i++) {
            List<UserBeauty> beautyList = player.getModule(BeautyModule.class).getUserBeautyListByOccupation(i + 1);
            int addition = 0;
            for (UserBeauty beauty : beautyList) {
                int identityLv = beauty.getIdentityLv();
                BeautyIdentityInfo identityInfo = BeautyMgr.getBeautyIdentityInfo(identityLv);
                addition += identityInfo.getApprenticeBonus();
            }
            finalList.add(newList.get(i) + addition);
        }

        return finalList;

    }

    private static int calcBaseTalent(MarriageRecord record, GrandChildData childData) {
        String[] arr = GameConfig.GRAND_CHILD_TALENT_PARENT_EARN_SPEED_PARAM.split("\\|");
        int quality = childData.getQuality();
        String s = arr[quality - 1];
        String[] paramArr = s.split(";");
        int param1 = Integer.parseInt(paramArr[0]);
        int param2 = Integer.parseInt(paramArr[1]);
        double m = new BigDecimal(param2).divide(new BigDecimal(1000), 4, BigDecimal.ROUND_UP).doubleValue();
        double baseValue = new BigDecimal(record.getTotalChildEarnSpeed()).multiply(new BigDecimal(param1)).divide(new BigDecimal(1000), 4, BigDecimal.ROUND_UP).doubleValue();
        double pow = Math.pow(baseValue, m);
        return (int) pow;
    }

    public static GrandChildUpgradeResult calcAddEarnSpeed(GamePlayer player, GrandChildData childData, boolean isBorn) {
        int occupation = childData.getOccupation();
        Integer flair = childData.getFlairList().get(occupation - 1);
        String[] arr = GameConfig.GRAND_CHILD_EARN_SPEED_PARAM.split("\\|");
        int randomValue = randomHelper.next(1, 5);
        if (randomValue == occupation) {
            randomValue += 1;
        }
        double param1 = Double.parseDouble(arr[0]);
        double param2 = Double.parseDouble(arr[1]);
        double param3 = Double.parseDouble(arr[2]);

        double randomParam = randomHelper.nextDouble(param1 / 1000, param2 / 1000);
        List<Integer> effectList = new ArrayList<>();
        int speedAddition = 0;
        if (!isBorn) {
            //只有普通升级才加成
            List<TalentTriggerResult> triggerTalentResult = TalentUtils.getTriggerTalentResult(childData, com.yanqu.road.server.manger.config.grandchild.talent.enums.eGrandChildSkillEffectStage.UPGRADE);
            TalentResultUtils.applyTalentAttrChange(childData, triggerTalentResult);
            speedAddition = TalentResultUtils.getEarnSpeedAddition(childData, triggerTalentResult);
            boolean topFloat = TalentResultUtils.getTopFloat(childData, triggerTalentResult);
            if (topFloat) {
                randomParam = param2 / 1000;
            }
            for (TalentTriggerResult result : triggerTalentResult) {
                if (result.isActive()) {
                    effectList.add(result.getTalentId());
                }
            }
            getLogger().info("schild: {},peedAddition: {}", childData.getId(), speedAddition);
        }
        double addEarnSpeed = (flair + childData.getFlairList().get(randomValue - 1)) * randomParam * param3 * (1 + speedAddition / 1000.0);
        return new GrandChildUpgradeResult(new BigDecimal(addEarnSpeed).setScale(0, BigDecimal.ROUND_UP).toBigInteger(), effectList);
    }

    public static int calcQualityChangeLv(int oldQuality, int newQuality) {
        String[] arr = GameConfig.GRAND_CHILD_QUALITY_LV.split("\\|");
        int oldLv = Integer.parseInt(arr[oldQuality - 1]);
        int newLV = Integer.parseInt(arr[newQuality - 1]);
        return newLV - oldLv;
    }


    public static List<Integer> getEffectTalentListBySkillType(GrandChildData childData, int skillType) {
        List<Integer> list = new ArrayList<>();
        for (Integer talentId : childData.getTalentList()) {
            GrandChildTalentInfo talentInfo = getGrandChildTalentInfo(talentId);
            for (Integer skill : talentInfo.getSkills()) {
                SkillInfo skillInfo = SkillMgr.getSkillInfo(skill);
                if (skillInfo.getType() == skillType) {
                    list.add(talentId);
                    break;
                }
            }
        }
        return list;
    }

    public static GrandChildTalentInfo getGrandChildTalentInfo(Integer talentId) {
        return grandChildTalentInfoMap.get(talentId);
    }

    public static boolean ReCalcArchaeus(GrandChildData childData) {
        int archaeus = childData.getArchaeus();
        //childData.setArchaeus(10000);
        CalcPowerResult result = PowerHelper.calcPower(childData.getArchaeusLastRecoverTime() / 1000, GameConfig.GRAND_CHILD_ARCHAEUS_RECOVER_TIME * 60, 1,
                GameConfig.GRAND_CHILD_ARCHAEUS_LIMIT, childData.getArchaeus());
        childData.setArchaeus(result.getCurPower());
        childData.setArchaeusLastRecoverTime(result.getLastRecoverTime() * 1000);
        if (result.getCurPower() != archaeus) {
            return true;
        }
        return false;
    }

    public static int getGraduationAddTeacherExp(GrandChildData childData, int addition) {
        int quality = childData.getQuality();
        String[] arr = GameConfig.GRAND_CHILD_GRADUATION_TEACHER_EXP.split("\\|");
        int baseValue = Integer.parseInt(arr[quality - 1]);
        double value = baseValue * (1 + addition / 1000.0);
        return (int) Math.round(value);
    }

    public static int getGraduationAddBaiYeExp(GrandChildData childData, int addition) {
        int quality = childData.getQuality();
        String[] arr = GameConfig.GRAND_CHILD_GRADUATION_BAIYE_EXP.split("\\|");
        int baseValue = Integer.parseInt(arr[quality - 1]);
        double value = baseValue * (1 + addition / 1000.0);
        return (int) Math.round(value);
    }


    @Override
    public boolean init() throws Exception {
        return reload();
    }

    @Override
    public boolean reloadConfig() throws Exception {
        openSchoolSiteConsumerList = new ArrayList<>();
        String[] arr = GameConfig.GRAND_CHILD_OPEN_SCHOOL_SITE.split("\\|");
        for (String s : arr) {
            BigInteger value = new BigInteger(s);
            openSchoolSiteConsumerList.add(value);
        }
        honeyMoonConsume = PropertyHelper.parseStringToProperty(GameConfig.GRAND_CHILD_HONEYMOON_CONSUME);
        grandChildTalentInfoMap = new GrandChildTalentInfoDaoImpl().getGrandChildTalentInfoMap();

        checkConfig();
        changeGroupConfig();
        return true;
    }

    public static void changeGroupConfig() {
        // 刷新分组配置
        int channelId = ServerListMgr.getChannelId(GameServer.getInstance().getServerId());
        if (channelId != 0) {
            Map<Integer, List<Long>> tmpGroupMap = GrandChildBussiness.getGrandChildGroupConfigMap(channelId);
            Map<Long, Integer> tmpServerMap = new ConcurrentHashMap<>();
            for (Map.Entry<Integer, List<Long>> entry : tmpGroupMap.entrySet()) {
                int groupId = entry.getKey();
                for (Long serverId : entry.getValue()) {
                    tmpServerMap.put(serverId, groupId);
                }
            }
            groupServerMap = tmpGroupMap;
            serverGroupMap = tmpServerMap;
        }
        if (isGrandChildOpen()) {
            for (GamePlayer player : GamePlayerMgr.getAllOnlinePlayer()) {
                player.getModule(PatronsModule.class).checkPatronsTeacherSkill(0);
            }
        }
    }

    public static boolean isGrandChildOpen() {
        long serverId = GameServer.getInstance().getServerId();
        Integer groupId = serverGroupMap.get(serverId);
        if (groupId != null && groupId > 0) {
            return true;
        }
        return false;
    }

    private void checkConfig() {
        Set<Integer> noExistList = new HashSet<>();
        for (GrandChildTalentInfo talentInfo : grandChildTalentInfoMap.values()) {
            List<Integer> skills = talentInfo.getSkills();
            for (Integer skillId : skills) {
                SkillInfo skillInfo = SkillMgr.getSkillInfo(skillId);
                if (skillInfo == null) {
                    noExistList.add(skillId);
                }
            }
        }
        if (noExistList.size() > 0) {
            System.err.println("技能配置不存在： " + noExistList);
        }
    }

    @Override
    public boolean reloadData() throws Exception {
        return true;
    }

    @Override
    public boolean stop() {
        return false;
    }

    /**
     * 获取孙子职业
     *
     * @return
     */
    public static int getGrandChildProfession(GrandChildData grandChildData) {
        return ChildMgr.getRandomOccupationId(grandChildData.getOccupation(), grandChildData.getSex(), false);
    }

    public static int grandChildNextLvNeedExp(GrandChildData childData) {
        int quality = childData.getQuality();
        int skillType = GrandChildConfigMgr.getSkillUpgradeType(quality);
        SkillUpgradeInfo upgradeInfo = SkillMgr.getSkillUpgradeInfo(skillType, childData.getLv());
        if (upgradeInfo == null || upgradeInfo.getConsumeCount() == 0) {
            //没有配置或者 满级了
            return 0;
        }
        long consumeCount = upgradeInfo.getConsumeCount();
        return (int) (consumeCount - childData.getTrainExp());
    }

    public static Set<Integer> previewActiveTalentList(GrandChildData childData, List<Integer> talentList) {
        GrandChildData clone = childData.clone();
        clone.setTalentList(talentList);

        List<TalentTriggerResult> triggerResultList = new ArrayList<>();
        triggerResultList.addAll(TalentUtils.getTriggerTalentResult(clone, eGrandChildSkillEffectStage.CHOICE_TALENT));
        TalentResultUtils.applyTalentAttrChange(clone, TalentUtils.getTriggerTalentResult(clone, eGrandChildSkillEffectStage.CHOICE_TALENT));
        GrandChildConfigMgr.confirmOccupation(clone);
        triggerResultList.addAll(TalentUtils.getTriggerTalentResult(clone, eGrandChildSkillEffectStage.UPGRADE));
        triggerResultList.addAll(TalentUtils.getTriggerTalentResult(clone, eGrandChildSkillEffectStage.GRADUATION));
        triggerResultList.addAll(TalentUtils.getTriggerTalentResult(clone, eGrandChildSkillEffectStage.EXAM));

        Set<Integer> activeList = new HashSet<>();
        for (TalentTriggerResult result : triggerResultList) {
            int talentId = result.getTalentId();
            if (activeList.contains(talentId)) {
                continue;
            }
            boolean isAffinityTalent = false;
            GrandChildTalentInfo info = GrandChildConfigMgr.getGrandChildTalentInfo(talentId);
            for (Integer skillId : info.getSkills()) {
                SkillInfo skillInfo = SkillMgr.getSkillInfo(skillId);
                if (skillInfo != null) {
                    if (skillInfo.getType() == eSkillType.GrandChildPatronsAbilityAddi.getValue()) {
                        //是授学门客天赋
                        isAffinityTalent = true;
                        int affinityPatronsId = clone.getAffinityPatronsId();
                        PatronsInfo patronsInfo = PatronsMgr.getPatronsInfo(affinityPatronsId);
                        if (patronsInfo != null && patronsInfo.getOccupation() == clone.getOccupation()) {
                            activeList.add(talentId);
                        }
                    }
                }
            }
            if (result.getSkillResultList().size() > 0 && !isAffinityTalent) {
                activeList.add(result.getTalentId());
            }
        }
        return activeList;
    }

    public static int getChildOccupation(int professionId){
        return professionId / 10000;
    }


    public static GrandChildOneKeyResult oneKeyActiveTalentRefresh2(GamePlayer player,GrandChildData childData,GrandChildOneKeyResult oneKeyResult){
        Property cost = PropertyHelper.parseStringToProperty(oneKeyResult.getCost());
        if(cost == null){
            cost = new Property();
        }
        Property consume = GrandChildConfigMgr.getReTalentConsume(childData.getReTalentTimes());
        //只刷第一次免费的
        if (childData.getReTalentTimes() == 0 && player.getModule(CurrencyModule.class).currencyIsEnough(consume)) {
            cost.addProperty(consume);
            player.getModule(CurrencyModule.class).removeCurrency(consume, eLogMoneyType.GrandChild, eLogMoneyType.ReTalentOneKey);
            List<Integer> logOldTalentList = new ArrayList<>(childData.getOptionalList()); // 日志用
            List<Integer> list = GrandChildConfigMgr.randomTalentList(player, childData);
            player.getModule(GrandChildModule.class).addTalentBook(list);
            childData.setOptionalList(list);
            childData.setReTalentTimes(childData.getReTalentTimes() + 1);
            // 日志
            AutoLogMgr.add(new LogGrandChildRefreshTalent(
                    player.getUserId(),
                    childData.getId(),
                    logOldTalentList,
                    childData.getOptionalList()
            ));
        }else{
            return oneKeyResult;
        }
        Map<Integer,Map<Integer,List<List<Integer>>>> resMap = getQa3TalentMap(childData);
        oneKeyResult.setCost(PropertyHelper.parsePropertyToString(cost));
        oneKeyResult.setAllChoice(resMap);
        return oneKeyResult;
    }


    private static Map<Integer,Map<Integer,List<List<Integer>>>> getQa3TalentMap(GrandChildData childData){
        //生效个数，生效的质量总和，三个技能对应多少
        Map<Integer,Map<Integer,List<List<Integer>>>> resMap = new ConcurrentHashMap<>();
        //三个一组的所有情况
        List<List<Integer>> goList = new ArrayList<>();
        List<Integer> optionalList = childData.getOptionalList();
        for(int a = 0;a < optionalList.size();a++){
            for(int b = a + 1;b < optionalList.size();b++){
                for(int c = b + 1;c < optionalList.size();c++){
                    List<Integer> addList = new ArrayList<>();
                    addList.add(optionalList.get(a));
                    addList.add(optionalList.get(b));
                    addList.add(optionalList.get(c));
                    goList.add(addList);
                }
            }
        }
        for(List<Integer> doList : goList){
            Set<Integer> activeList = previewActiveTalentList(childData,doList);
            if(!resMap.containsKey(activeList.size())){
                resMap.put(activeList.size(),new ConcurrentHashMap<>());
            }
            int allQaCount = 0;
            List<Integer> tList = new ArrayList<>();
            for(int talentId : doList){
                GrandChildTalentInfo info = GrandChildConfigMgr.getGrandChildTalentInfo(talentId);
                allQaCount = allQaCount + info.getQuality();
                tList.add(talentId);
            }
            if(!resMap.get(activeList.size()).containsKey(allQaCount)){
                resMap.get(activeList.size()).put(allQaCount,new ArrayList<>());
            }
            resMap.get(activeList.size()).get(allQaCount).add(tList);
        }
        return resMap;
    }

    //第二次优化
    public static GrandChildOneKeyResult oneKeyActiveTalentList2(GamePlayer player, GrandChildData childData) {
        GrandChildOneKeyResult oneKeyResult = new GrandChildOneKeyResult();
        Map<Integer,Map<Integer,List<List<Integer>>>> allChoiceMap = getQa3TalentMap(childData);
        oneKeyResult.setAllChoice(allChoiceMap);
        oneKeyResult.setoOptionList(childData.getOptionalList());
        if(!allChoiceMap.containsKey(3)){
            oneKeyResult = oneKeyActiveTalentRefresh2(player,childData,oneKeyResult);
        }
        oneKeyResult.setOptionList(childData.getOptionalList());
        allChoiceMap = oneKeyResult.getAllChoice();
        List<Integer> activeCountList = new ArrayList<>(allChoiceMap.keySet());
        Collections.sort(activeCountList);
        Collections.reverse(activeCountList);
        List<Integer> qaCountList = new ArrayList<>(allChoiceMap.get(activeCountList.get(0)).keySet());
        Collections.sort(qaCountList);
        Collections.reverse(qaCountList);
        //有多个一样的取第一个
        List<Integer> choiceList = allChoiceMap.get(activeCountList.get(0)).get(qaCountList.get(0)).get(0);
        oneKeyResult.setChoiceList(choiceList);

        oneKeyResult.setOldChildData(childData.clone());
        oneKeyResult.getOldChildData().setTalentList(oneKeyResult.getChoiceList());
        return oneKeyResult;
    }
}
